package com.bifrost.service;

import com.bifrost.constant.BonusPointsUpdatedType;
import com.bifrost.entity.BonusPointsHistory;
import com.bifrost.entity.Customer;
import com.bifrost.entity.MerchantStore;
import com.bifrost.excel.model.BondsInfo;
import com.bifrost.model.vo.PageVO;
import com.bifrost.repository.BonusPointsHistoryRepository;
import com.bifrost.repository.CustomerRepository;
import com.bifrost.repository.MerchantStoreRepository;
import com.bifrost.repository.OrderRepository;
import com.bifrost.util.DateUtils;
import lombok.extern.log4j.Log4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@Log4j
@Service
public class MerchantBonusService {
    @Autowired
    private BonusPointsHistoryRepository bonusPointsHistoryRepository;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    MerchantStoreRepository merchantStoreRepository;
    public PageVO queryBonusReport(Integer page, Integer pageSize, String startTime, String endTime, String cardNumber, String name, String phone, List<Long> storeIds){
        Pageable pageRequest = new PageRequest(page-1,pageSize,new Sort(Sort.Direction.DESC,"bonusPointsHistory"));
        List<String> cardNumbers = toQueryCardNumber(phone, name, storeIds,cardNumber);
        Page<BonusPointsHistory> historyPage = bonusPointsHistoryRepository.findAll(getSpecification(startTime, endTime, cardNumbers, storeIds), pageRequest);
        Long totalElements = historyPage.getTotalElements();
        List<BondsInfo> infoList = assembe(historyPage.getContent());
        return new PageVO(page, pageSize, totalElements.intValue(), infoList);
    }
    public List<BondsInfo> queryBonusReport(String startTime, String endTime, String cardNumber,String name, String phone,List<Long> storeIds){
        List<String> cardNumbers = toQueryCardNumber(phone, name, storeIds, cardNumber);
        List<BonusPointsHistory> historyList = bonusPointsHistoryRepository.findAll(getSpecification(startTime, endTime, cardNumbers,storeIds));
        return assembe(historyList);
    }
    private List<String> toQueryCardNumber(String phone,String name,List<Long> storeIds,String cardNumber){
        List<String> cardNumbers = new ArrayList<>();
        if(StringUtils.isNotBlank(phone)){
/*            for (Long merchantStoreId:storeIds
                    ) {
                Customer customer = customerRepository.findCustomerByPhone(merchantStoreId,phone);
                if(customer!=null){
                    cardNumbers.add(customer.getLoyaltyCard());
                }
            }*/
            cardNumbers.add(customerRepository.findFirstByCustomerPhone(phone).getLoyaltyCard());
        }
        if(StringUtils.isNotBlank(name)){
            for (Long merchantStoreId:storeIds
                    ) {
                List<String> cardNumberList = customerRepository.findCardNumberByNameLikeAndStoreId("%"+name+"%",merchantStoreId);
                cardNumbers.addAll(cardNumberList);
            }
            log.info(Arrays.toString(cardNumbers.toArray()));
        }
        if(cardNumber!=null){
            cardNumbers.add(cardNumber);
        }
        while (cardNumbers.remove(null)){}
        while(cardNumbers.remove("")){}
        return cardNumbers;
    }

    public Page<BonusPointsHistory> bonusInfoPage(String startTime, String endTime, String cardNumber,String name, String phone,List<Long> storeIds,Integer page, Integer pageSize){
        List<String> cardNumbers = toQueryCardNumber(phone, name, storeIds, cardNumber);
        Pageable pageRequest = new PageRequest(page-1,pageSize);
        return bonusPointsHistoryRepository.findAll(getSpecification(startTime, endTime, cardNumbers,storeIds), pageRequest);
    }

    private List<BondsInfo> assembe(List<BonusPointsHistory> historyList){
        List<BondsInfo> list = new ArrayList<>();
        Integer index = 0;
        for (BonusPointsHistory bonusPointsHistory:historyList
                ) {
            index++;
            BondsInfo bondsInfo = new BondsInfo();
            String orderNum = bonusPointsHistory.getNumber();
/*            if(orderNum.equals("0000000000000")){
                bondsInfo.setDescription("门店管理员修改");
            }
            bondsInfo.setDescription(orderRepository.findDescByNum(orderNum));*/
            String cardNumber1 = bonusPointsHistory.getCardNumber();
            bondsInfo.setSerialNumber(index.toString());
            bondsInfo.setCardNumber(cardNumber1);
            bondsInfo.setPhone(bonusPointsHistory.getCustomerPhone());
            bondsInfo.setCustomerName(bonusPointsHistory.getCustomerLastName());
            if(bonusPointsHistory.getUpdatedType().equals(BonusPointsUpdatedType.INCREMENT)){
                bondsInfo.setBonus("+"+bonusPointsHistory.getUpdatedValue());
            }else if(bonusPointsHistory.getUpdatedType().equals(BonusPointsUpdatedType.DECREMENT)){
                bondsInfo.setBonus("-"+bonusPointsHistory.getUpdatedValue());
            }

            bondsInfo.setDate(DateUtils.formatDate(bonusPointsHistory.getUpdatedTimestamp()));
            bondsInfo.setRemark(bonusPointsHistory.getRemark());
            bondsInfo.setCreateBy(bonusPointsHistory.getCreateBy());
            MerchantStore merchantStore = merchantStoreRepository.findOne(bonusPointsHistory.getMerchantId());
            bondsInfo.setStoreName(("[" + merchantStore.getExternalId() + "]" + merchantStore.getStoreName()));
            list.add(bondsInfo);
        }
        return list;
    }

    private Specification<BonusPointsHistory> getSpecification(String startTime, String endTime,List<String> cardNumbers, List<Long> storeIds){
        return new Specification<BonusPointsHistory>() {
            @Override
            public Predicate toPredicate(Root<BonusPointsHistory> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if(!StringUtils.isBlank(startTime)){
                    Path<Date> queryStartCreateTime = root.get("updatedTimestamp");
                    Date startDate = DateUtils.parse(startTime, DateUtils.DEFAULT_DATE_FORMAT);
                    predicates.add(cb.greaterThanOrEqualTo(queryStartCreateTime,startDate));
                }
                if(!StringUtils.isBlank(endTime)){
                    Path<Date> queryEndCreateTime = root.get("updatedTimestamp");
                    Date endData = DateUtils.parse(endTime, DateUtils.DEFAULT_DATE_FORMAT);
                    predicates.add(cb.lessThanOrEqualTo(queryEndCreateTime,endData));
                }
                if(CollectionUtils.isNotEmpty(cardNumbers)){
                    Path<String> queryCardNumber = root.get("cardNumber");
                    predicates.add(queryCardNumber.in(cardNumbers));
                }
                if(CollectionUtils.isNotEmpty(storeIds)){
                    Path<Long> queryStoreId = root.get("merchantId");
                    predicates.add(queryStoreId.in(storeIds));
                }
                Predicate[] p = new Predicate[predicates.size()];
                return cb.and(predicates.toArray(p));
            }
        };
    }
}
